﻿#pragma once

#include <QString>
#include <QLibrary>
#include <QSharedPointer>


// dll库加载方式， 0：使用QT加载，1：使用win32 API加载，2:使用库的lib文件编译时确定地址
#define LoadType 0


#define UseStructDefineOutside
#if defined(UseStructDefineOutside) || (2 == LoadType)
#include "ControlCAN/ControlCAN.h"
#endif




class CanDeviceDriver : public QObject
{
	Q_OBJECT
public:
#ifndef UseStructDefineOutside
	enum EnumDeviceType
	{
		VCI_USBCAN1 = 3,
		VCI_USBCAN2 = 4,
		VCI_USBCAN2A = 4,

		VCI_USBCAN_E_U = 20,
		VCI_USBCAN_2E_U = 21,
	};
	enum EnumStatus
	{
		//函数调用返回状态值
		STATUS_OK = 1,
		STATUS_ERR = 0,
	};
#endif
#ifndef UseStructDefineOutside
	//1.ZLGCAN系列接口卡信息的数据类型。
	typedef  struct  _VCI_BOARD_INFO {
		unsigned short	hw_Version;
		unsigned short	fw_Version;
		unsigned short	dr_Version;
		unsigned short	in_Version;
		unsigned short	irq_Num;
		unsigned char	can_Num;
		char	str_Serial_Num[20];
		char	str_hw_Type[40];
		unsigned short	Reserved[4];
	} VCI_BOARD_INFO, *PVCI_BOARD_INFO;

	//2.定义CAN信息帧的数据类型。
	typedef  struct  _VCI_CAN_OBJ {
		unsigned int	ID;
		unsigned int	TimeStamp;
		unsigned char	TimeFlag;
		unsigned char	SendType;
		unsigned char	RemoteFlag;//是否是远程帧
		unsigned char	ExternFlag;//是否是扩展帧
		unsigned char	DataLen;
		unsigned char	Data[8];
		unsigned char	Reserved[3];
	}VCI_CAN_OBJ, *PVCI_CAN_OBJ;

	//3.定义初始化CAN的数据类型
	typedef struct _VCI_INIT_CONFIG {
		unsigned long	AccCode;
		unsigned long	AccMask;
		unsigned long	Reserved;
		unsigned char	Filter;
		unsigned char	Timing0;
		unsigned char	Timing1;
		unsigned char	Mode;
	}VCI_INIT_CONFIG, *PVCI_INIT_CONFIG;
#endif

	// 函数类型定义
	typedef unsigned long(__stdcall *VCI_OpenDevice_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long Reserved);
	typedef unsigned long(__stdcall *VCI_CloseDevice_Define)(unsigned long DeviceType, unsigned long DeviceInd);
	typedef unsigned long(__stdcall *VCI_InitCAN_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd, PVCI_INIT_CONFIG pInitConfig);

	typedef unsigned long(__stdcall *VCI_ReadBoardInfo_Define)(unsigned long DeviceType, unsigned long DeviceInd, PVCI_BOARD_INFO pInfo);

	typedef unsigned long(__stdcall *VCI_SetReference_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd, unsigned long RefType, void * pData);

	typedef unsigned long(__stdcall *VCI_GetReceiveNum_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd);
	typedef unsigned long(__stdcall *VCI_ClearBuffer_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd);

	typedef unsigned long(__stdcall *VCI_StartCAN_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd);
	typedef unsigned long(__stdcall *VCI_ResetCAN_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd);

	typedef unsigned long(__stdcall *VCI_Transmit_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd, PVCI_CAN_OBJ pSend, unsigned long Len);
	typedef unsigned long(__stdcall *VCI_Receive_Define)(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd, PVCI_CAN_OBJ pReceive, unsigned long Len, int WaitTime);
public:
	CanDeviceDriver();
	virtual ~CanDeviceDriver();
public:
	// 实例
	static QSharedPointer<CanDeviceDriver> instance();
public:
	// 加载DLL
	void UnloadDLL();
	bool LoadDLL(QString dllFilePath);
private:
#if LoadType == 0
	// QT库
	QLibrary mlib;
#elif LoadType == 1
	// win32 API加载后库句柄
	void * handleDll = NULL;
#endif
public:
	// 函数
	VCI_OpenDevice_Define VCI_OpenDevice = nullptr;
	VCI_CloseDevice_Define VCI_CloseDevice = nullptr;
	VCI_InitCAN_Define VCI_InitCAN = nullptr;
	VCI_ReadBoardInfo_Define VCI_ReadBoardInfo = nullptr;
	VCI_SetReference_Define VCI_SetReference = nullptr;
	VCI_GetReceiveNum_Define VCI_GetReceiveNum = nullptr;
	VCI_ClearBuffer_Define VCI_ClearBuffer = nullptr;
	VCI_StartCAN_Define VCI_StartCAN = nullptr;
	VCI_ResetCAN_Define VCI_ResetCAN = nullptr;
	VCI_Transmit_Define VCI_Transmit = nullptr;
	VCI_Receive_Define VCI_Receive = nullptr;
};

